package com.computer.spring.framework.aop;

import com.computer.spring.framework.aop.intercept.BYMethodInvocation;
import com.computer.spring.framework.aop.support.BYAdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * @Description
 * @Author MagicIce
 * @Date 2020/11/22 16:25
 */
public class BYJdkDynamicAopProxy implements BYAopProxy, InvocationHandler {

    private BYAdvisedSupport config;

    public BYJdkDynamicAopProxy(BYAdvisedSupport config) {
        this.config = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(this.config.getTargetClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader, this.config.getTargetClass().getInterfaces(), this);
    }

    /** invoke() 方法是执行代理的关键入口 */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /** 将每一个 JoinPoint 也就是被代理的业务方法(Method)封装成一个拦截器，组合成一个拦截器链 */
        List<Object> interceptorsAndDynamicMethodMatchers = config.getInterceptorsAndDynamicInterceptionAdvice(method, this.config.getTargetClass());
        /** 交给拦截器链 MethodInvocation 的 proceed() 方法执行 */
        BYMethodInvocation invocation = new BYMethodInvocation(proxy, this.config.getTarget(), method, args,
                this.config.getTargetClass(), interceptorsAndDynamicMethodMatchers);
        return invocation.proceed();
    }
}
